﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using System.Runtime.CompilerServices;
using Microsoft.CSharp.RuntimeBinder;

using Alicanto.Helpers;

namespace Alicanto.Compilation.Code.Operators.Numeric
{
    internal class OpAdd : ICodeGenerator
    {
        public Expression Code { get; private set; }

        public IEnumerable<ParseInstruction> Generate(TokenSequence tokens, Scope scope)
        {
            GetEvaluation evaluation = new GetEvaluation();
            yield return evaluation;

            ParseExpressionRemainder remainder = new ParseExpressionRemainder();
            yield return remainder;

            Expression x = evaluation.Expression;
            Expression y = remainder.Remainder;

            // Dynamic
            if (x.Type == typeof(object) || y.Type == typeof(object))
            {
                this.Code = Expression.Dynamic(
                    Binding.CreateBinaryBinder(ExpressionType.Add),
                    typeof(object),
                    x,
                    y
                );
            }
            // Number + Number
            else if (Typing.IsNumber(x.Type) && Typing.IsNumber(y.Type))
            {
                Conversion.EqualizeNumbers(ref x, ref y);
                this.Code = Expression.Add(
                    x,
                    y
                );
            }
            // String + String
            else
            {
                x = Conversion.EnsureString(x);
                y = Conversion.EnsureString(y);

                this.Code = Expression.Call(
                    null,
                    typeof(string).GetMethod(
                        "Concat", 
                        new Type[] { 
                            typeof(string), 
                            typeof(string) 
                        }
                    ),
                    x,
                    y
                );
            }
        }
    }
}
